home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio / DSeqChildApp.cpp < prev    next >
Text File  |  1996-07-05  |  28KB  |  1,045 lines

  1. // DSeqChildApp.cpp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include "DSeqChildApp.h"
  6.  
  7. #include <ncbi.h>
  8. #include <dgg.h>
  9. #include <Dvibrant.h>
  10. #include <DControl.h>
  11. #include <DApplication.h>
  12. #include <DTask.h>
  13. #include <DMenu.h>
  14. #include <DPanel.h>
  15. #include <DUtil.h>
  16. #include <DWindow.h>
  17. #include <DChildApp.h>
  18. #include <DChildDlogDoc.h>
  19. #include <DRichMoreStyle.h>
  20. #include <DRichViewNu.h>
  21. #include <DNetObject.h>
  22. #include <DBOPclient.h>
  23. #include <DURL.h>
  24.  
  25. #include "DSeqFile.h"
  26. #include "DSeqList.h"
  27. #include "DSeqDoc.h"
  28. #include "DSeqAsmDoc.h"
  29.  
  30.  
  31.  
  32.  
  33. // !! many of these SeqChildApp methods should go inti ChildApp class
  34.  
  35. class DSeqChildApp : public DChildApp
  36. {
  37. public:
  38.     //char  * fName, * fCmdline;
  39.     //const char * fStdin, * fStdout, * fStderr;
  40.     enum seqactions { kOpenSequence = 11, kOpenTree, kOpenAutoseq };
  41.     char     * fMenuname, * fDescription, * fSeqformat, *fHelpfile;
  42.     char    * fForm, * fFormName;
  43.     ulong        fFormLength;
  44.     short        fMinseq, fMaxseq, fMenucmd;
  45.     DChildFile * fInfile;
  46.     char        fFileType[128];
  47.     Boolean    fSaveFiletype, fDeleteWhenDone;
  48.     
  49.     DSeqChildApp() :
  50.         DChildApp(),
  51.         fMenuname(NULL), fDescription(NULL), fSeqformat(NULL), fHelpfile(NULL),
  52.         fInfile(NULL), fMinseq(0), fMaxseq(0), fMenucmd(0), 
  53.         fFormName(NULL), fForm(NULL), fFormLength(0), fSaveFiletype(false),
  54.         fDeleteWhenDone(true)
  55.         {
  56.             //fFiles= new DList();
  57.             fFileType[0]= '\0';
  58.         }
  59.     virtual ~DSeqChildApp();
  60.     virtual void LaunchDialog( DSeqList* aSeqList); 
  61.     virtual void LaunchAfterDialog( DSeqList* aSeqList); 
  62.     virtual void FileAction( DChildFile* aFile);
  63.     virtual void CollectOptions( DList* optList);
  64.     virtual char* CollectFilePath(char* value, Boolean checkOutType, short& action);
  65.     virtual char* SubstituteVars(char* data, DList* optList);
  66.     virtual char* SubstituteAppID(char* data);
  67. };
  68.  
  69.  
  70.  
  71.  
  72.  
  73. // class DLaunchDialog
  74.  
  75. class DLaunchDialog : public DWindow {
  76.     enum { cHELP = 3222 };
  77.     char *fHelpfile;
  78.     DSeqChildApp* fChild;
  79. public: 
  80.     DLaunchDialog( DSeqChildApp* child);
  81.     virtual void Open();            
  82.     virtual Nlm_Boolean IsMyAction(DTaskMaster* action); 
  83. };
  84.         
  85.         
  86.         
  87. DLaunchDialog::DLaunchDialog( DSeqChildApp* child) :
  88.     DWindow( 0, gApplication, fixed, -10, -10, -50, -20, "Launch app"),
  89.     fChild(child)
  90.     {
  91.     }
  92.  
  93. void DLaunchDialog::Open()
  94. {
  95.     char buf[128];
  96.     
  97.     if (fChild->fDescription) { 
  98.         DCluster* clu= new DCluster( 0, this, 0, 0, false, "Description");   //0,0 == wid,hi
  99.         new DNotePanel(0, clu, fChild->fDescription, 200, 50);    
  100.         this->NextSubviewBelowLeft();
  101.         }
  102.     sprintf( buf, "Launch %s?",fChild->fMenuname);
  103.     new DPrompt(0, this, buf, 0, 0, Nlm_systemFont);             
  104.     this->NextSubviewBelowLeft();
  105.             
  106.     this->AddOkayCancelButtons(cOKAY,"Launch",cCANC,"Cancel");
  107.     if (fChild->fHelpfile) {
  108.         fHelpfile= fChild->fHelpfile;
  109.         this->NextSubviewToRight();
  110.         new DButton( cHELP, this, "Help");
  111.         }
  112.     else
  113.         fHelpfile= NULL;
  114.         
  115.     DWindow::Open();
  116. }
  117.  
  118. Nlm_Boolean DLaunchDialog::IsMyAction(DTaskMaster* action) 
  119. {    
  120.     switch(action->Id()) {
  121.         case cHELP:
  122.             gApplication->OpenDocument(fHelpfile);
  123.             return true;
  124.         default:
  125.             return DWindow::IsMyAction(action);    
  126.         }
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135. DSeqChildApp::~DSeqChildApp()
  136. {
  137.     MemFree( fMenuname);
  138.     MemFree( fDescription);
  139.     MemFree( fSeqformat);
  140.     MemFree( fHelpfile);
  141.     MemFree( fFormName);
  142.     MemFree( fForm);
  143. }
  144.  
  145.  
  146. enum { kDistanceMat = -89, kSimilarityMat, kBiotree, kTracefile };
  147.  
  148. void DSeqChildApp::LaunchDialog( DSeqList* aSeqList) 
  149. {
  150.     DLaunchDialog* win= NULL;
  151.     Boolean okay= true;
  152.     
  153. #ifdef WIN_MAC
  154.         // This works for MAC but fails for MSWIN && UNIX!
  155.     win= new DLaunchDialog(this);
  156.     okay= win->PoseModally();
  157.     delete win;  // for MSWin, MUST delete win BEFORE LAUNCH !! -- now mswin fails here
  158. #else
  159. #if defined( WIN_MOTIF ) || defined( WIN_MSWIN)
  160.     // bad problems in Unix/XWin w/ this dialog mangling child launch process...
  161.     okay= true;
  162. #else        
  163.         // this works for MSWIN but fails on MAC !
  164.     DLaunchDialog ldlog(this);
  165.     okay= ldlog.PoseModally();
  166. #endif
  167. #endif
  168.  
  169.     if (okay) LaunchAfterDialog( aSeqList);
  170. }
  171.  
  172.  
  173. void DSeqChildApp::LaunchAfterDialog( DSeqList* aSeqList) 
  174. {
  175.     if (fMinseq>0 && (!aSeqList || aSeqList->GetSize()<fMinseq)) {
  176.         Message(MSG_OK, "%s needs a selection of at least %d sequences", 
  177.                             fMenuname, fMinseq);
  178.         return;
  179.         }
  180.     if (fMaxseq>0 && (!aSeqList || aSeqList->GetSize()>fMaxseq)) {
  181.         Message(MSG_OK, "%s needs a selection of no more than %d sequence(s)", 
  182.                             fMenuname, fMaxseq);
  183.         return;
  184.         }
  185.             // write aSeqList to this->inputfile...
  186.     DFile* aFile = this->fInfile;
  187.     if (aFile && this->fInfile->fDelete) {
  188.         char  * data = NULL;
  189.         short  outformat= 0;
  190.         
  191.         if (StrNICmp(fSeqformat, "distance", 8)==0) outformat= kDistanceMat;
  192.         else if (StrNICmp(fSeqformat, "tracefile", 9)==0) {
  193.             outformat= kTracefile;
  194.             goto doLaunch;
  195.             }
  196.         else if (StrNICmp(fSeqformat, "similar", 7)==0) outformat= kSimilarityMat;
  197.         else if (StrNICmp(fSeqformat, "biotree", 7)==0) outformat= kBiotree;
  198.         else outformat= DSeqFile::FormatFromName(fSeqformat);
  199.         if (outformat == DSeqFile::kUnknown) outformat= DSeqFile::kPearson; 
  200.  
  201.         if (aSeqList) aSeqList->ClearSelections(); //! make sure we write all of seq from this call !?
  202.         switch (outformat) {
  203.         
  204.             case kSimilarityMat:
  205.                 if (!aSeqList) return;
  206.                 data= aSeqList->Similarities(DSeqDoc::fgDistCor);  
  207.                 break;
  208.                 
  209.             case kDistanceMat:
  210.                 if (!aSeqList) return;
  211.                 data= aSeqList->Distances(DSeqDoc::fgDistCor); 
  212.                 break;
  213.                 
  214.             case kBiotree:
  215.                 {
  216.                         // data is text in front richtext window !?
  217.                 DRichTextDoc* rtdoc = (DRichTextDoc*) gWindowManager->CurrentWindow();
  218.                 aFile->Open("w");
  219.                 rtdoc->fRichView->Save(aFile);
  220.                 }
  221.                 break;
  222.                 
  223.             default:
  224.                 if (!aSeqList) return;
  225.                 DSeqFile::DontSaveMasks();
  226.                 aFile->Open("w");
  227.                 aSeqList->DoWrite( aFile, outformat);
  228.                 DSeqFile::DoSaveMasks();
  229.                 break;
  230.             }
  231.             
  232.         if (data) {
  233.             ulong count= StrLen(data);
  234.             aFile->Open("w");
  235.             aFile->WriteData( data, count);
  236.             MemFree(data);
  237.             }
  238.         aFile->Close();
  239.         aFile->SetMode("r");
  240.         }
  241.         
  242. doLaunch:    
  243.     if (!this->Launch())
  244.         Message(MSG_OK, "Failed to launch %s with '%s'", fName, fCmdline);
  245.       
  246. }
  247.  
  248.  
  249.  
  250. void DSeqChildApp::FileAction( DChildFile* aFile)
  251. {
  252.     switch (aFile->fAction) {
  253.       case kOpenSequence:
  254.             DSeqDoc::fgTestSeqFile= true; // ???
  255.             gApplication->OpenDocument( aFile);
  256.             DSeqDoc::fgTestSeqFile= false; 
  257.             if (aFile->fDelete) {
  258.                 DWindow* win= gWindowManager->CurrentWindow();
  259.                 if (win && win->fSaveHandler) win->fSaveHandler->Dirty();
  260.                 }
  261.             break;
  262.             
  263.         case kOpenAutoseq: {
  264.             DSeqAsmDoc::fgTestAutoseqFile= true;  
  265.             gApplication->OpenDocument( aFile);
  266.             DSeqAsmDoc::fgTestAutoseqFile= false; 
  267.             if (aFile->fDelete) {
  268.                 DWindow* win= gWindowManager->CurrentWindow();
  269.                 if (win && win->fSaveHandler) win->fSaveHandler->Dirty();
  270.                 }
  271.             }
  272.             break;
  273.             
  274.       case kOpenTree:
  275.           // fix later...
  276.         default:
  277.             DChildApp::FileAction( aFile);
  278.             break;
  279.         }
  280. }
  281.  
  282.  
  283.  
  284.  
  285. char* DSeqChildApp::CollectFilePath(char* value, Boolean checkOutType, short& action)
  286. {
  287.     fSaveFiletype  = false;
  288.     fDeleteWhenDone= true;
  289.     if (checkOutType) {
  290.         char* ftype= StrChr(value,'\t'); // look for mime/type after name
  291.         if (!ftype) ftype= StrChr(value,' '); // !? can we also scan for spaces ??
  292.         if (ftype) {
  293.             *ftype++= 0;
  294.             while (*ftype && *ftype <= ' ') ftype++;
  295.             if (StrNICmp(ftype,"biosequence",11) == 0 
  296.              || StrNICmp(ftype,"sequence",8) == 0)
  297.                     action= DSeqChildApp::kOpenSequence;
  298.                     
  299.             else if (StrNICmp(ftype,"autoseq",7) == 0) {
  300.                 action= DSeqChildApp::kOpenAutoseq;
  301.                 StrNCpy( fFileType, ftype, sizeof(fFileType));
  302.                 fSaveFiletype= true;
  303.                 fDeleteWhenDone= false;
  304.                 }
  305.                     
  306.             else if (StrNICmp(ftype,"biotree",7) == 0 
  307.              || StrNICmp(ftype,"tree",4) == 0)
  308.                     action= DSeqChildApp::kOpenTree;
  309.             }
  310.         }
  311.         
  312.     char* cp= value; 
  313.     while (isspace(*cp) || *cp == '$') cp++;
  314.     
  315.         // check for special infile (for ChooseFile...)
  316.     if (fInfile && StrNICmp( cp,"infile",6)==0) { 
  317.         char* np= StrDup( fInfile->GetName());
  318.         StrExtendCat( &np, cp+6);
  319.         return np;
  320.         }
  321.     else
  322.         return gApplication->ConvertStdFilePath(cp);
  323. }                
  324.  
  325.  
  326.  
  327. char* DSeqChildApp::SubstituteVars(char* data, DList* optList)
  328. {
  329.     char * cp, * item, * value, * newpath;
  330.     short action, kind;
  331.     DControlStyle* cont;
  332.     
  333.     data= SubstituteAppID(data);
  334.     if (!optList) return data;
  335.     short i, nopts= optList->GetSize();
  336.     
  337.     for (i=0; i<nopts; i++) {
  338.             // pass 1, collect non-hidden control vars == user opts
  339.             
  340.         cont= (DControlStyle*) optList->At(i);
  341.         item = (char*)cont->Varname();
  342.         value= (char*)cont->Value();
  343.         kind= cont->fKind;
  344.  
  345.         if (item && kind != DControlStyle::kHidden) { 
  346.             Boolean istest, dosub;
  347.             char * ep, * dp, * itemp, * iteme;
  348.             char * trueval, * falseval;
  349.             char * newvalue = StrDup("");
  350.             long itemsize= StrLen(item);
  351.             dp= cp = data;
  352.             do {
  353.                 istest= false;
  354.                 dosub= false;
  355.                 trueval= falseval= NULL;
  356.                 ep= StrChr( dp, '$');
  357.                 if (!ep)
  358.                     StrExtendCat( &newvalue, cp);
  359.                 else {
  360.                     if (ep[1] == '{' /*}*/) { 
  361.                         itemp= ep+2; 
  362.                         iteme= itemp; 
  363.                         while (*iteme && *iteme != /*{*/'}') iteme++;
  364.                         if (iteme - itemp != itemsize) itemp= NULL; 
  365.                         if (*iteme == /*{*/'}') iteme++; 
  366.                         }
  367.                     else if (ep[1] == '?') {
  368.                         // $?var1:valtrue:valfalse  -> ($var)?valtrue:valfalse
  369.                         itemp= ep+2;
  370.                         iteme= itemp + itemsize;
  371.                         istest= true;
  372.                         }
  373. #if 0
  374.                     else if (ep[1] == '$') {
  375.                         // '$$' == process ID, or AppID() !
  376.                         value= (char*) gApplication->AppID();  
  377.                         dosub= true;
  378.                         itemp= ep+1;
  379.                         itemsize= 1;
  380.                         iteme= ep+2;
  381.                         }
  382. #endif
  383.                     else {
  384.                         itemp= ep+1;
  385.                         iteme= itemp + itemsize;
  386.                         }
  387.                         
  388.                     if (itemp && (dosub || StrNICmp( item, itemp, itemsize) == 0)) {
  389.                         if (istest) {
  390.                             trueval= iteme;
  391.                             if (*trueval == ':') {
  392.                                 *trueval++= ' ';
  393.                                 }
  394.                             falseval= StrChr(trueval,':');
  395.                             if (falseval) {
  396.                                 *falseval++ = ' ';
  397.                                 iteme= StrChr(falseval,':');
  398.                                 if (iteme) *iteme++ = ' ';
  399.                                 else iteme= itemp + itemsize;
  400.                                 }
  401.                             }
  402.                         *ep++ = 0;
  403.                         StrExtendCat( &newvalue, cp);  // add on string before '$'
  404.                         if (value) {
  405.                             if (trueval) iteme= trueval; //StrExtendCat( &newvalue, trueval);
  406.                             else StrExtendCat( &newvalue, value);
  407.                             }
  408.                         else {
  409.                             if (falseval) iteme= falseval;
  410.                             }
  411.                         // else we drop the variable marker !
  412.                         cp= dp= iteme;
  413.                         }
  414.                     else
  415.                         dp= ep+1;
  416.                         
  417.                     }
  418.             } while (ep);
  419.             MemFree( data);
  420.             data= newvalue;
  421.             }
  422.         }
  423.     return data;
  424. }
  425.                 
  426.                 
  427. char* DSeqChildApp::SubstituteAppID(char* data)
  428. {    
  429.     // change $$ variable only !?!?!
  430.     char * cp, * ep, * dp;
  431.     
  432.     dp= cp = data;
  433.     ep= StrStr( dp, "$$");
  434.     if (!ep) return data;
  435.  
  436.     char * newvalue = StrDup("");
  437.     do {
  438.         ep= StrChr( dp, '$');
  439.         if (!ep)
  440.             StrExtendCat( &newvalue, cp);
  441.         else {
  442.             if (ep[1] == '$') {
  443.                 // '$$' == process ID, or AppID() !
  444.                 char* value= (char*) gApplication->AppID(); //tmpnam(NULL);
  445.                 char* iteme= ep+2;
  446.  
  447.                 *ep++ = 0;
  448.                 StrExtendCat( &newvalue, cp);  // add on string before '$'
  449.                 if (value) StrExtendCat( &newvalue, value);
  450.                 // else we drop the variable marker !
  451.                 cp= dp= iteme;
  452.                 }
  453.             else
  454.                 dp= ep+1;
  455.             }
  456.     } while (ep);
  457.     MemFree( data);
  458.     return newvalue;
  459. }
  460.                 
  461.                 
  462. void DSeqChildApp::CollectOptions( DList* optList)
  463. {
  464.     char * cp, * item, * value, * newpath;
  465.     short action, kind, i, nopts;
  466.     DControlStyle* cont;
  467.     char * execapp = NULL;
  468.     DChildFile         * cfile;
  469.     Boolean     noStderr= true, noStdout= true, noStdin= true;
  470.     
  471.     if (!optList) return;
  472.     
  473.     nopts= optList->GetSize();
  474.     for (i=0; i<nopts; i++) {
  475.             // pass 0, collect command line !
  476.             
  477.         cont= (DControlStyle*) optList->At(i);
  478.         item = (char*)cont->Varname();
  479.         value= (char*)cont->Value();
  480.         if (value) while (isspace(*value)) value++;
  481.         kind= cont->fKind;
  482.         
  483.         if (item && value) {
  484.          if (kind == DControlStyle::kHidden) { 
  485.             if (StrICmp(item,"localexec")==0 || StrICmp(item,"exec")==0) {
  486.                 execapp= StrDup(value);
  487.                 fCallMethod= kLocalexec;
  488.                 }
  489.             else if (StrICmp(item,"bop")==0 || StrICmp(item,"bopexec")==0) {
  490.                 execapp= StrDup(value);
  491. #if 1
  492.                 // do variable substitution in execapp for $bophost, ? $bopport
  493.                 // by the way, looks like optList is a memory leak -- is no one deleting it?
  494.                 DControlStyle* cs;
  495.                 char sport[80];
  496.                 sprintf( sport, "%d", DBOP::gPort);
  497.                 cs= new DControlStyle(NULL);
  498.                 cs->ControlData( "bophost", DBOP::gHost);
  499.                 optList->InsertLast( cs);
  500.                 cs= new DControlStyle(NULL);
  501.                 cs->ControlData( "bopport", sport);
  502.                 optList->InsertLast( cs);
  503. #endif
  504.  
  505.                 fCallMethod= kBOPexec;
  506.                 if (!fNob) fNob = new DNetOb();
  507.                 }
  508.             else if (StrICmp(item,"get")==0) {
  509.                 execapp= StrDup(value);
  510.                 fCallMethod= kHTTPget;
  511.                 }
  512.             else if (StrICmp(item,"post")==0) {
  513.                 execapp= StrDup(value);
  514.                 fCallMethod= kHTTPpost;
  515.                 }
  516.             }
  517.         else if (kind == DControlStyle::kFileChooser) {
  518.             if (StrICmp(item,"infile")==0) {// option for more than 1 infile ??
  519.                             // value == full pathname (?) - split into path + name??
  520.                 // ?? need "rb" or "rt" flag??
  521.                 newpath= value;
  522.                 cfile= new DChildFile( newpath, DChildFile::kInput, DChildFile::kDontDelete,
  523.                                           DChildFile::kNoAction, "rb", "????", "????");
  524.                 AddFile(cfile);
  525.                 fInfile= cfile; 
  526.                 }
  527.             }
  528.         else if ( StrICmp(item, "user") == 0) {
  529.             if (!fNob) fNob = new DNetOb();
  530.             fNob->StoreUser( value);
  531.             }
  532.         else if ( StrICmp(item, "password") == 0) {
  533.             if (!fNob) fNob = new DNetOb();
  534.             fNob->StorePass( value);
  535.             }
  536.             
  537.             
  538.          }
  539.         }
  540.     if (!execapp) return; // ??
  541.     
  542.     execapp= SubstituteVars( execapp, optList);
  543.         
  544.         // cut app + options into 2 parts
  545.     cp= execapp;
  546.     while (*cp && !isspace(*cp)) cp++;
  547.     if (*cp) *cp++= 0;
  548.     MemFree( fName);
  549.     if (fCallMethod == kLocalexec)
  550.         fName= CollectFilePath( execapp, false, action);
  551.     else
  552.         fName= StrDup( execapp);
  553.         
  554.         // substitute full file paths in cmdline 
  555.     {
  556.         while (*cp && !isspace(*cp)) cp++;
  557.         char * ep;
  558.         char * newvalue = StrDup("");
  559.         do {
  560.             ep= StrChr( cp, '$');
  561.             if (ep) {
  562.                 *ep++ = 0;
  563.                 StrExtendCat( &newvalue, cp);  // add on string before '$'
  564.                     // find & substitute any pathname
  565.                 char savec, *np= ep; 
  566.                 while (isgraph(*ep)) ep++; 
  567.                 savec= *ep; *ep= 0; // skip past path:filename
  568.                 
  569.                 // check for special infile (for ChooseFile...)
  570.                 if (fInfile && StrICmp( np,"infile")==0)  
  571.                     newpath= StrDup( fInfile->GetName());
  572.                 else
  573.                     newpath= gApplication->ConvertStdFilePath(np);
  574.                 *ep= savec;
  575.                 if (newpath && *newpath) {
  576.                     char* dquote= NULL;
  577.                     if (StrChr( newpath, ' ')) {
  578.                         dquote= "'";
  579.                         // ! must find start of parameter, e.g. [/infile=$temp:data]
  580.                         //  where newpath is for $temp:data, requires we start quote 
  581.                         // at ['/infile=new path:data']
  582.                         char* pp= newvalue + StrLen(newvalue);
  583.                         while (pp > newvalue && isspace(*pp)) pp--;
  584.                         while (pp > newvalue && !isspace(*pp)) pp--;
  585.                         if (isspace(*pp)) {
  586.                             *pp++= 0;
  587.                             char* saveparm= StrDup(pp); // extend(newval) will wipe out pp !
  588.                             StrExtendCat( &newvalue, dquote);
  589.                             StrExtendCat( &newvalue, saveparm);
  590.                             MemFree( saveparm);
  591.                             }
  592.                         else
  593.                             StrExtendCat( &newvalue, dquote);
  594.                         }
  595.                     StrExtendCat( &newvalue, newpath);
  596.                     if (dquote) StrExtendCat( &newvalue, dquote);
  597.                     MemFree( newpath);
  598.                     }
  599.                 else {
  600.                     // this is another variable not replaced above... 
  601.                     // it is deleted from fCmdline
  602.                     }
  603.                     
  604.                 cp= ep;
  605.                 }
  606.             else
  607.                 StrExtendCat( &newvalue, cp);
  608.         } while (ep);
  609.         MemFree( fCmdline);
  610.         fCmdline= newvalue;
  611.     }
  612.     MemFree( execapp);
  613.  
  614.     
  615.     nopts= optList->GetSize();
  616.     for (i=0; i<nopts; i++) {
  617.             // pass 2, collect only hidden control vars == DSeqChildApp vars
  618.             
  619.         cont= (DControlStyle*) optList->At(i);
  620.         item = (char*)cont->Varname();
  621.         value= (char*)cont->Value();
  622.         kind= cont->fKind;
  623.  
  624.         if (item && value && kind == DControlStyle::kHidden) { 
  625.                 // !? ignore all controls w/ NULL value !?
  626.  
  627.             if (StrICmp(item,"seqformat")==0)     {
  628.                 MemFree(fSeqformat);
  629.                 fSeqformat= StrDup(value);
  630.                 }
  631.                 
  632. #if 0        
  633.             else if (StrICmp(item,"path")==0) {
  634.                 MemFree(fName);
  635.                 fName= CollectFilePath(value, false, action);
  636.                 }
  637. #endif
  638.  
  639.             else if (StrICmp(item,"stdcmdin")==0) {
  640.                 noStdin= false;
  641.                 newpath= CollectFilePath( "$temp:stdcmdin", false, action);
  642.                 cfile= new DChildFile( newpath, DChildFile::kStdin, DChildFile::kDeleteWhenDone,
  643.                                                                 DChildFile::kNoAction, "r", "TEXT", "Spup");
  644.  
  645.                  // stuff value into file...
  646.                 value= SubstituteVars( StrDup(value), optList);
  647.                 ulong count= StrLen(value);
  648.                 cfile->Open("w");
  649.                 cfile->WriteData( value, count);
  650.                 cfile->Close();
  651.                 MemFree( value);
  652.                 //fInfile= cfile;  
  653.                 AddFile(cfile);
  654.                 MemFree( newpath);
  655.                 }
  656.                                                     
  657.             else if (StrICmp(item,"minseq")==0) {
  658.                 fMinseq= atoi(value);
  659.                 }
  660.  
  661.             else if (StrICmp(item,"maxseq")==0) {
  662.                 fMaxseq= atoi(value);
  663.                 }
  664.                                             
  665.             else if (StrNICmp(item,"infile",6)==0) {
  666.                 value= SubstituteAppID( StrDup(value)); //??
  667.                 newpath= CollectFilePath( value, false, action);
  668.                 cfile= new DChildFile( newpath, DChildFile::kInput, DChildFile::kDeleteWhenDone,
  669.                                                                 DChildFile::kNoAction, "r", "TEXT", "Spup");
  670.                 AddFile(cfile);
  671.                 fInfile= cfile; 
  672.                 MemFree( newpath);
  673.                 MemFree( value);
  674.                 }
  675.  
  676.             else if (StrNICmp(item,"stdin",5)==0) {
  677.                 value= SubstituteAppID( StrDup(value)); //??
  678.                 noStdin= false;
  679.                 newpath= CollectFilePath( value, false, action);
  680.                 cfile= new DChildFile( newpath, DChildFile::kStdin, DChildFile::kDeleteWhenDone,
  681.                                                                 DChildFile::kNoAction, "r", "TEXT", "Spup");
  682.                 fInfile= cfile;  
  683.                 AddFile(cfile);
  684.                 MemFree( newpath);
  685.                 MemFree( value);
  686.                 }
  687.  
  688.             else if (StrNICmp(item,"stderr",6)==0) {
  689.                 value= SubstituteAppID( StrDup(value)); //??
  690.                 noStderr= false;
  691.                 action = DChildFile::kOpenText;
  692.                 newpath= CollectFilePath( value, true, action);
  693.                 cfile= new DChildFile( newpath, DChildFile::kStderr, DChildFile::kDeleteWhenDone,
  694.                                                                 action, "r", "TEXT", "Spup");
  695.                 AddFile(cfile);
  696.                 MemFree( newpath);
  697.                 MemFree( value);
  698.                 }
  699.  
  700.             else if (StrNICmp(item,"stdout",6)==0) {
  701.                 value= SubstituteAppID( StrDup(value)); //??
  702.                 noStdout= false;
  703.                 action = DChildFile::kOpenText;
  704.                 newpath= CollectFilePath( value, true, action);
  705.                 cfile= new DChildFile( newpath, DChildFile::kStdout, DChildFile::kDeleteWhenDone,
  706.                                                                 action, "r", "TEXT", "Spup");
  707.                 AddFile(cfile);
  708.                 MemFree( newpath);
  709.                 MemFree( value);
  710.                 }
  711.  
  712.             else if (StrNICmp(item,"outfile",7)==0) {
  713.                 char *ftype;
  714.                 value= SubstituteAppID( StrDup(value)); //??
  715.                 action = DChildFile::kOpenText;
  716.                 newpath= CollectFilePath( value, true, action);
  717.                 if (fSaveFiletype) ftype= StrDup(fFileType); // LEAK!  need to delete DFile.fType !!
  718.                 else ftype= "TEXT"; 
  719.                 cfile= new DChildFile( newpath, DChildFile::kOutput, fDeleteWhenDone,
  720.                                                                 action, "r", ftype, "Spup");
  721.                 AddFile( cfile);
  722.                 MemFree( newpath);
  723.                 MemFree( value);
  724.                 }
  725.                                 
  726.             }    
  727.         }
  728.     
  729.     if (noStderr)    AddFile(DChildFile::kStderr, NULL);
  730.     if (noStdout)    AddFile(DChildFile::kStdout, NULL);
  731. }
  732.     
  733.     
  734.  
  735.  
  736. // class DSeqApps : public DObject
  737.  
  738.  
  739. // static
  740. void DSeqApps::CallChildApp(short menucmd, DSeqList* aSeqList) 
  741. {
  742.     DChildDlogDoc* doc = NULL;
  743.     DSeqChildApp * child = NULL;
  744.     short i, n = DChildAppManager::gChildList->GetSize();
  745.     for (i= 0; i<n; i++) {
  746.         child= (DSeqChildApp*) DChildAppManager::gChildList->At(i);
  747.         if (child->fMenucmd == menucmd) {
  748.  
  749.             if (child->fForm || child->fFormName) {
  750.                 if (1) { // !child->fForm) // ?? always read form?
  751.                     //doc->Open(child->fFormName);
  752.                     char* fbuf;
  753.                     ulong flen;
  754.                     DFile ff(child->fFormName);
  755.                     ff.Open();
  756.                     ff.GetDataLength(flen);
  757.                     if (!flen) return;
  758.                     fbuf= (char*) MemNew(flen+1);
  759.                     ff.ReadData(fbuf, flen);
  760.                     ff.Close();
  761.                     fbuf[flen]= 0;
  762.                     child->fFormLength= flen;
  763.                     MemFree( child->fForm); 
  764.                     child->fForm= fbuf;
  765.                     }
  766.                     //?? child->LaunchAfterForm( aSeqList);
  767.                 doc= new DChildDlogDoc( 0, false, gTextFont);
  768.                 doc->OpenText(child->fForm, child->fFormLength);
  769.                 Boolean okay= doc->PoseModally();
  770.                 
  771.                     // collect user options from doc controls !
  772.                 if (okay) child->CollectOptions(doc->GetControls());
  773.                 delete doc;   
  774.                 
  775.                 if (okay) child->LaunchAfterDialog( aSeqList);
  776.                 }
  777.             else 
  778.                 child->LaunchDialog( aSeqList); // old method
  779.                 
  780.             return;
  781.             }
  782.         }
  783.     Message(MSG_OK, "Child app not found");
  784. }
  785.  
  786.  
  787. char * DSeqApps::kAppSection = "apps";
  788.  
  789. // static
  790. void DSeqApps::SetUpMenu( short menuId, DMenu*& aMenu, char* menuPrefs) 
  791. {
  792.     static short menuitem= kChildMenuBaseID;
  793.     long     atsection;
  794.     ulong sectlen = 0;
  795.     char    * value, * item, * appsection, * appvalues, * sections,
  796.                 * newpath,  * cp;
  797.     DSeqChildApp     * child;
  798.     DChildFile         * cfile;
  799.     Boolean     noStderr= true, noStdout= true, noStdin= true;
  800.     
  801.     
  802.     //DWindow::SetUpMenu(menuId, aMenu);
  803.     if (!aMenu) aMenu = gApplication->NewMenu( menuId, "ChildApps");
  804.  
  805.     sections= gApplication->GetPrefSection( menuPrefs, sectlen);
  806.     atsection= 0;
  807.     while (atsection<sectlen) {
  808.         appsection= sections + atsection;
  809.         if (appsection) {
  810.             long     atvalue;
  811.             ulong applen= 0;
  812.             
  813.             child= new DSeqChildApp();
  814.             // child is stored in DChildAppManager::gChildList
  815.             
  816.             value= gApplication->GetPref( appsection, menuPrefs);
  817.             if (!value) value= StrDup( appsection);
  818.             aMenu->AddItem( menuitem, value);
  819.             child->fMenuname= value;
  820.             child->fMenucmd= menuitem;
  821.             menuitem++;
  822.     
  823.             child->fReusable= true; // don't delete after one use...
  824.         
  825.             appvalues= gApplication->GetPrefSection( appsection, applen);
  826.             atvalue= 0;
  827.             while (atvalue<applen) {
  828.                 item= appvalues + atvalue;
  829.                 value= gApplication->GetPref( item, appsection);
  830.                 
  831.                 if (!value)
  832.                     ;
  833.                 else if (StrICmp(item,"form")==0) {
  834.                         // FORM IS ONLY TAG NOW USED !!  
  835.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  836.                     child->fFormName= gApplication->ConvertStdFilePath(cp);
  837.                     MemFree( value);
  838.                     }
  839.                 else if (StrICmp(item,"desc")==0)  
  840.                     child->fDescription= value;
  841.                 else if (StrICmp(item,"path")==0) {
  842.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  843.                     child->fName= gApplication->ConvertStdFilePath(cp);
  844.                     MemFree( value);
  845.                     }
  846.                 else if (StrICmp(item,"help")==0) {
  847.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  848.                     child->fHelpfile= gApplication->ConvertStdFilePath(cp);
  849.                     MemFree( value);
  850.                     }
  851.                     
  852.                 else if (StrICmp(item,"seqformat")==0)     
  853.                     child->fSeqformat= value;
  854.                 else if (StrICmp(item,"minseq")==0) {
  855.                     child->fMinseq= atoi(value);
  856.                     MemFree( value);
  857.                     }
  858.                 else if (StrICmp(item,"maxseq")==0) {
  859.                     child->fMaxseq= atoi(value);
  860.                     MemFree( value);
  861.                     }
  862.             
  863.                 else if (StrICmp(item,"cmd")==0)    {
  864.                     // convert variables of form $word[delimiter] ...
  865.                     // especially file path variables
  866.                     char * ep;
  867.                     char * newvalue = StrDup("");
  868.                     cp = value;
  869.                     do {
  870.                         ep= StrChr( cp, '$');
  871.                         if (ep) {
  872.                             *ep++ = 0;
  873.                             StrExtendCat( &newvalue, cp);  // add on string before '$'
  874.                             
  875.                                 // find & substitute any pathname
  876.                             newpath= gApplication->ConvertStdFilePath(ep);
  877.                                 // newpath is all of remaining string ... cut pathname from remainder of str
  878.                             //char* np= newpath;
  879.                             //while (isgraph(*np)) np++;  *np= 0;
  880.                             StrExtendCat( &newvalue, newpath);
  881.                             MemFree( newpath);
  882.                             
  883.                                 // locate next part of str to parse -- cue on whitespace
  884.                             while (isgraph(*ep)) ep++;  
  885.                             cp= ep;
  886.                             }
  887.                         else
  888.                             StrExtendCat( &newvalue, cp);
  889.                     } while (ep);
  890.                     MemFree( value);
  891.                     value= newvalue;
  892.                     child->fCmdline= value;
  893.                     }
  894.                     
  895.                     // need also to handle dialog control items !!, e.g., dlog=control spec...
  896.                     // and need to handle dlog control substitutions in cmdline...
  897.                             
  898.                 else if (StrNICmp(item,"infile",6)==0) {
  899.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  900.                     newpath= gApplication->ConvertStdFilePath(cp);
  901.                     cfile= new DChildFile( newpath, DChildFile::kInput, DChildFile::kDeleteWhenDone,
  902.                                                                     DChildFile::kNoAction, "r", "TEXT", "Spup");
  903.                     child->AddFile(cfile);
  904.                     child->fInfile= cfile;  
  905.                     MemFree( newpath);
  906.                     MemFree( value);
  907.                     }
  908.  
  909.                 else if (StrNICmp(item,"stdin",5)==0) {
  910.                     noStdin= false;
  911.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  912.                     newpath= gApplication->ConvertStdFilePath(cp);
  913.                     cfile= new DChildFile( newpath, DChildFile::kStdin, DChildFile::kDontDelete,
  914.                                                                     DChildFile::kNoAction, "r", "TEXT", "Spup");
  915.                     child->AddFile(cfile);
  916.                     child->fInfile= cfile;  
  917.                     MemFree( newpath);
  918.                     MemFree( value);
  919.                     }
  920.  
  921.                 else if (StrNICmp(item,"stderr",6)==0) {
  922.                     noStderr= false;
  923.                     short action = DChildFile::kOpenText;
  924.                     char* ftype= StrChr(value,'\t'); // look for mime/type after name
  925.                     if (!ftype) ftype= StrChr(value,' '); // !? can we also scan for spaces ??
  926.                     if (ftype) {
  927.                         *ftype++= 0;
  928.                         while (*ftype && *ftype <= ' ') ftype++;
  929.                         if (StrNICmp(ftype,"biosequence",11) == 0 
  930.                          || StrNICmp(ftype,"sequence",8) == 0)
  931.                                 action= DSeqChildApp::kOpenSequence;
  932.                         else if (StrNICmp(ftype,"biotree",7) == 0 
  933.                          || StrNICmp(ftype,"tree",4) == 0)
  934.                                 action= DSeqChildApp::kOpenTree;
  935.                         }
  936.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  937.                     newpath= gApplication->ConvertStdFilePath(cp);
  938.                     cfile= new DChildFile( newpath, DChildFile::kStderr, DChildFile::kDontDelete,
  939.                                                                     action, "r", "TEXT", "Spup");
  940.                     child->AddFile(cfile);
  941.                     MemFree( newpath);
  942.                     MemFree( value);
  943.                     }
  944.  
  945.                 else if (StrNICmp(item,"stdout",6)==0) {
  946.                     noStdout= false;
  947.                     short action = DChildFile::kOpenText;
  948.                     char* ftype= StrChr(value,'\t'); // look for mime/type after name
  949.                     if (!ftype) ftype= StrChr(value,' '); // !? can we also scan for spaces ??
  950.                     if (ftype) {
  951.                         *ftype++= 0;
  952.                         while (*ftype && *ftype <= ' ') ftype++;
  953.                         if (StrNICmp(ftype,"biosequence",11) == 0 
  954.                          || StrNICmp(ftype,"sequence",8) == 0)
  955.                                 action= DSeqChildApp::kOpenSequence;
  956.                         else if (StrNICmp(ftype,"biotree",7) == 0 
  957.                          || StrNICmp(ftype,"tree",4) == 0)
  958.                                 action= DSeqChildApp::kOpenTree;
  959.                         }
  960.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  961.                     newpath= gApplication->ConvertStdFilePath(cp);
  962.                     cfile= new DChildFile( newpath, DChildFile::kStdout, DChildFile::kDontDelete,
  963.                                                                     action, "r", "TEXT", "Spup");
  964.                     child->AddFile(cfile);
  965.                     MemFree( newpath);
  966.                     MemFree( value);
  967.                     }
  968.                     
  969.                 else if (StrNICmp(item,"outfile",7)==0) {
  970.                     // combine stdout & stderr w/ this code...
  971.                     short action = DChildFile::kOpenText;
  972.                     char* ftype= StrChr(value,'\t'); // look for mime/type after name
  973.                     if (!ftype) ftype= StrChr(value,' '); // !? can we also scan for spaces ??
  974.                     if (ftype) {
  975.                         *ftype++= 0;
  976.                         while (*ftype && *ftype <= ' ') ftype++;
  977.                         if (StrNICmp(ftype,"biosequence",11) == 0 
  978.                          || StrNICmp(ftype,"sequence",8) == 0)
  979.                                 action= DSeqChildApp::kOpenSequence;
  980.                         else if (StrNICmp(ftype,"biotree",7) == 0 
  981.                          || StrNICmp(ftype,"tree",4) == 0)
  982.                                 action= DSeqChildApp::kOpenTree;
  983.                         }
  984.                     cp= value; while (isspace(*cp) || *cp == '$') cp++;
  985.                     newpath= gApplication->ConvertStdFilePath(cp);
  986.                     cfile= new DChildFile( newpath, DChildFile::kOutput, DChildFile::kDontDelete,
  987.                                                                     action, "r", "TEXT", "Spup");
  988.                     child->AddFile(cfile);
  989.                     MemFree( newpath);
  990.                     MemFree( value);
  991.                     }
  992.                     
  993.             
  994.                 atvalue += StrLen(item)+1;
  995.                 }
  996.  
  997. #if 0            
  998.     // not w/ CollectOptions() doing same thing !
  999.             if (noStderr) child->AddFile(DChildFile::kStderr, NULL);
  1000.             if (noStdout) child->AddFile(DChildFile::kStdout, NULL);
  1001. #endif
  1002.             
  1003.             MemFree( appvalues);
  1004.             }
  1005.         atsection += StrLen(appsection)+1;
  1006.         }
  1007.     MemFree( sections);
  1008. }
  1009.  
  1010.  
  1011.  
  1012.  
  1013. #if 0
  1014.  
  1015.             /////// prefs file example ///////
  1016. [apps]
  1017. ;localvar=menu title
  1018. clustal=Multiple align...
  1019. cap=Contig assembly...
  1020. dnaml=Phylip DNAML...
  1021.  
  1022. [clustal]
  1023. ;file path to application 
  1024. path=apps:clustalw
  1025. help=apps:clustalw_help
  1026. ;description for dialog
  1027. desc=A multiple sequence alignment application
  1028. ;dialog controls (HTML forms format?)
  1029.  
  1030. ;command line switches
  1031. cmd=/infile=temp:clustal.inseq /outfile=clustal.outseq /output=gcg /align
  1032.  
  1033. ;sequence selection to input file 
  1034. infile=clustal.inseq
  1035. ;sequence format to send to app
  1036. seqformat=nbrf
  1037. ;minimum number of selected sequences to activate this command
  1038. minseq=2
  1039. ;return data files, with doc/type
  1040. outfile1=clustal.outseq    text/plain
  1041. outfile2=clustal.dnd    text/plain
  1042.  
  1043.  
  1044. #endif
  1045.